package system_services

import (
	"context"
	"fmt"
	"go_ruoyi/global"
	"go_ruoyi/model/db_model"
	"go_ruoyi/model/request_model"
	"go_ruoyi/model/response_model"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
)

var StatusMap = map[string]string{"0": "正常", "2": "停用"}
var SexMap = map[string]string{"0": "男", "1": "女", "2": "未知"}

func GetUserList(c *gin.Context) {
	var (
		RequestUser request_model.QueryUser
		userList    []*db_model.User
		totalCount  int64
	)

	if err := c.ShouldBindQuery(&RequestUser); err != nil {
		response_model.FailWithMsg(c, "参数错误")
		return
	}
	if err := global.DB.Model(&db_model.User{}).Count(&totalCount).Error; err != nil {
		response_model.FailWithData(c, err)
		return
	}

	offset := (RequestUser.PageNum - 1) * RequestUser.PageSize
	if err := global.DB.Preload("Dept").Where(&RequestUser).Where("del_flag = ?", 0).Offset(offset).Limit(RequestUser.PageSize).Find(&userList).Error; err != nil {
		response_model.FailWithData(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code":  200,
		"rows":  userList,
		"msg":   "查询成功",
		"total": totalCount,
	})
}

func GetUserById(c *gin.Context) {

	userID := c.Param("id")
	var (
		postList []*db_model.Post
		roleList []*db_model.Role
		user     db_model.User
	)

	if err := global.DB.Find(&postList).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	if err := global.DB.Find(&roleList).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	if err := global.DB.Preload("Dept").Preload("Roles").Preload("Posts").Where("user_id = ?", userID).First(&user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	roleIds := make([]int64, 0)
	for i := 0; i < len(user.Roles); i++ {
		roleIds = append(roleIds, user.Roles[i].RoleID)
	}
	postIds := make([]int64, 0)
	for i := 0; i < len(user.Posts); i++ {
		postIds = append(postIds, user.Posts[i].PostId)
	}
	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"msg":     "操作成功",
		"posts":   postList,
		"roles":   roleList,
		"data":    user,
		"postIds": postIds,
		"roleIds": roleIds,
	})

}

// 根据ID获取user
func GetUser(cxt *gin.Context) {
	userID := cxt.Param("id")
	var (
		postList []*db_model.Post
		roleList []*db_model.Role
		user     db_model.User
	)

	if err := global.DB.Find(&postList).Error; err != nil {
		cxt.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	if err := global.DB.Find(&roleList).Error; err != nil {
		cxt.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	if userID == "" {
		cxt.JSON(http.StatusOK, gin.H{
			"code":  200,
			"msg":   "操作成功",
			"posts": postList,
			"roles": roleList,
		})
		return
	}
	if err := global.DB.Preload("Dept").Preload("Roles").Preload("Posts").Where("user_id = ?", userID).First(&user).Error; err != nil {
		cxt.JSON(http.StatusInternalServerError, gin.H{
			"error": "服务器异常",
		})
		return
	}
	roleIds := make([]int64, 0)
	for i := 0; i < len(user.Roles); i++ {
		roleIds = append(roleIds, user.Roles[i].RoleID)
	}
	postIds := make([]int64, 0)
	for i := 0; i < len(user.Posts); i++ {
		postIds = append(postIds, user.Posts[i].PostId)
	}
	cxt.JSON(http.StatusOK, gin.H{
		"code":    200,
		"msg":     "操作成功",
		"posts":   postList,
		"roles":   roleList,
		"data":    user,
		"postIds": postIds,
		"roleIds": roleIds,
	})
}

// 新增
func CreateUser(c *gin.Context) {
	var (
		AddUser request_model.AddUser
		Roles   []db_model.Role
		Posts   []db_model.Post
	)
	UpdateUserName, _ := c.Get("userName")
	if err := c.ShouldBindJSON(&AddUser); err != nil {
		response_model.FailWithMsg(c, "参数错误")
		return
	}
	if err := global.DB.Find(&Roles, "role_id in ?", AddUser.RoleIds).Error; err != nil {
		response_model.FailWithMsg(c, "查不到关联角色")
		log.Fatalln("查不到关联角色:", err)
		return
	}
	if err := global.DB.Find(&Posts, "post_id in ?", AddUser.PostIds).Error; err != nil {
		response_model.FailWithMsg(c, "查不到关联岗位")
		log.Fatalln("查不到关联岗位:", err)
		return
	}

	if err := global.DB.WithContext(context.WithValue(context.Background(), global.UserContextKey, UpdateUserName)).Create(&db_model.User{
		UserName:    AddUser.UserName,
		NickName:    AddUser.NickName,
		Password:    AddUser.Password,
		Email:       AddUser.Email,
		Phonenumber: AddUser.Phonenumber,
		Sex:         AddUser.Sex,
		DeptId:      AddUser.DeptId,
		Roles:       Roles,
		Posts:       Posts,
		Common: db_model.Common{
			Status: AddUser.Status,
		},
	}).Error; err != nil {
		response_model.FailWithMsg(c, "新增失败")
		return
	}
	response_model.OK(c, "新增成功")
}

// 编辑
func UpdateUser(c *gin.Context) {
	var (
		AddUser request_model.AddUser
		Roles   []db_model.Role
		Posts   []db_model.Post
		User    db_model.User
	)
	if err := c.ShouldBindJSON(&AddUser); err != nil {
		response_model.FailWithMsg(c, "参数错误")
		return
	}
	UpdateUserName, _ := c.Get("userName")

	User = db_model.User{
		UserId:      AddUser.UserId,
		UserName:    AddUser.UserName,
		NickName:    AddUser.NickName,
		Email:       AddUser.Email,
		Phonenumber: AddUser.Phonenumber,
		Sex:         AddUser.Sex,
		DeptId:      AddUser.DeptId,
		Common: db_model.Common{
			Status: AddUser.Status,
		},
		Roles: Roles,
		Posts: Posts,
	}

	TX := global.DB.Begin()

	if err := TX.Find(&Roles, "role_id in ?", AddUser.RoleIds).Error; err != nil {
		response_model.FailWithMsg(c, "查不到关联角色")
		log.Fatalln("查不到关联角色:", err)
		return
	}
	if err := TX.Find(&Posts, "post_id in ?", AddUser.PostIds).Error; err != nil {
		response_model.FailWithMsg(c, "查不到关联岗位")
		log.Fatalln("查不到关联岗位:", err)
		return
	}

	if err := TX.WithContext(context.WithValue(context.Background(), global.UserContextKey, UpdateUserName)).Where("user_id = ?", AddUser.UserId).Updates(&User).Error; err != nil {
		response_model.FailWithMsg(c, "编辑失败")
		TX.Rollback()
		return
	}

	if err := TX.Model(&User).Association("Roles").Replace(Roles); err != nil {
		response_model.FailWithMsg(c, "编辑失败")
		TX.Rollback()
		return
	}
	if err := TX.Model(&User).Association("Posts").Replace(Posts); err != nil {
		response_model.FailWithMsg(c, "编辑失败")
		TX.Rollback()
		return
	}
	TX.Commit()
	response_model.OK(c, "编辑成功")
}

// 删除
func DeleteUser(c *gin.Context) {
	var (
		User db_model.User
	)
	userID := c.Param("id")
	if err := global.DB.Where("user_id = ?", userID).First(&User).Error; err != nil {
		response_model.FailWithMsg(c, "查不到该用户")
		return
	}
	User.DelFlag = 2
	if err := global.DB.Select("del_flag").Updates(&User).Error; err != nil {
		response_model.FailWithMsg(c, "删除失败")
		return
	}
	response_model.OK(c, "删除成功")
}

// 重置密码
func ResetPwd(c *gin.Context) {
	var (
		AddUser request_model.AddUser
		User    db_model.User
	)
	if err := c.ShouldBindJSON(&AddUser); err != nil {
		response_model.FailWithMsg(c, "参数错误")
		return
	}
	UpdateUserName, _ := c.Get("userName")

	User.Password = AddUser.Password
	User.UpdateBy = UpdateUserName.(string)
	User.UpdateTime = time.Now()
	User.UserId = AddUser.UserId
	if err := global.DB.Debug().WithContext(context.WithValue(context.Background(), global.UserContextKey, UpdateUserName)).Where("user_id = ?", AddUser.UserId).Updates(&User).Error; err != nil {
		response_model.FailWithMsg(c, "重置密码失败")
		return
	}
	response_model.OK(c, "重置密码成功")
}

// 导出
func ExportUser(c *gin.Context) {
	var (
		RequestUser request_model.QueryUser
		userList    []*db_model.User
		totalCount  int64
	)
	if err := c.ShouldBind(&RequestUser); err != nil {
		response_model.FailWithData(c, err)
		return
	}
	fmt.Println(RequestUser)
	if err := global.DB.Model(&db_model.User{}).Count(&totalCount).Error; err != nil {
		response_model.FailWithData(c, err)
		return
	}

	offset := (RequestUser.PageNum - 1) * RequestUser.PageSize
	if err := global.DB.Preload("Dept").Where(&RequestUser).Where("del_flag = ?", 0).Offset(offset).Limit(RequestUser.PageSize).Find(&userList).Error; err != nil {
		response_model.FailWithData(c, err)
		return
	}
	// 创建一个新的 Excel 文件
	f := excelize.NewFile()

	// 添加工作表
	sheetName := "用户数据"
	index, _ := f.NewSheet(sheetName)
	f.SetActiveSheet(index)

	// 设置表头
	headers := []string{"用户序号", "登录名称", "用户名称", "用户邮箱", "手机号码", "用户性别", "账号状态", "最后登录IP", "最后登录时间", "部门名称", "部门负责人"}
	for i, header := range headers {
		ex, err := excelize.ColumnNumberToName(i + 1)
		if err != nil {
			response_model.FailWithData(c, err)
			return
		}
		cell := fmt.Sprintf("%s1", ex)
		f.SetCellValue(sheetName, cell, header)
	}
	// 写入用户数据
	for rowIndex, user := range userList {
		rowIndex++ // 跳过表头行
		f.SetCellValue(sheetName, fmt.Sprintf("A%d", rowIndex+1), user.UserId)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", rowIndex+1), user.UserName)
		f.SetCellValue(sheetName, fmt.Sprintf("C%d", rowIndex+1), user.NickName)
		f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowIndex+1), user.Email)
		f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowIndex+1), user.Phonenumber)
		f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowIndex+1), SexMap[user.Sex])
		f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowIndex+1), StatusMap[user.Status])
		f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowIndex+1), user.LoginIp)
		f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowIndex+1), user.LoginDate)

		f.SetCellValue(sheetName, fmt.Sprintf("J%d", rowIndex+1), user.Dept.DeptName)
		f.SetCellValue(sheetName, fmt.Sprintf("K%d", rowIndex+1), user.Dept.Leader)

	}
	fmt.Println(userList)
	// 设置响应头，告诉浏览器这是一个文件下载
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", "attachment; filename=用户数据.xlsx")
	c.Header("File-Name", "用户数据.xlsx")

	// 将 Excel 文件写入响应体
	writer := c.Writer
	if err := f.Write(writer); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "无法生成 Excel 文件"})
		return
	}
}

// 导入
func ImportUser(c *gin.Context) {
	// 获取上传的文件
	file, err := c.FormFile("file")
	if err != nil {
		response_model.FailWithMsg(c, "上传文件失败")
		return
	}
	f, _ := file.Open()
	defer f.Close()
	// 打开文件
	excelFile, err := excelize.OpenReader(f)
	if err != nil {
		response_model.FailWithMsg(c, "打开文件失败")
		return
	}
	defer excelFile.Close()

	// 读取第一个工作表的数据
	rows, err := excelFile.GetRows("用户数据")
	if err != nil {
		response_model.FailWithMsg(c, "读取数据失败")
		return
	}
	if len(rows) == 1 { // 确保至少有一行数据(除去表头)
		response_model.FailWithMsg(c, "导入的数据不能为空")
		return
	}
	// 准备存储用户数据的切片
	var users []db_model.User

	// 遍历每一行数据并构建 User 结构体
	for i, row := range rows {
		if i == 0 { // 跳过表头行
			continue
		}

		deptId, err := strconv.ParseInt(row[0], 10, 64)
		if err != nil {
			response_model.FailWithMsg(c, "部门ID格式错误")
			return
		}
		var sex string
		switch row[5] {
		case "男":
			sex = "0"
		case "女":
			sex = "1"
		default:
			sex = "2"
		}
		var status string
		switch row[6] {
		case "正常":
			row[6] = "0"
		case "停用":
			row[6] = "1"
		}
		users = append(users, db_model.User{
			DeptId:      deptId,
			UserName:    row[1],
			NickName:    row[2],
			Email:       row[3],
			Phonenumber: row[4],
			Sex:         sex,
			Common:      db_model.Common{Status: status},
		})

	}

	// 使用 GORM 批量插入数据
	if err := global.DB.Create(&users).Error; err != nil {

		c.JSON(http.StatusOK, gin.H{"code": 500, "msg": "数据异常"})
		return
	}
	var msgStr string
	for i, v := range users {
		msgStr += fmt.Sprintf("%d、账号 %s 导入成功<br/>", i+1, v.UserName)
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": fmt.Sprintf("恭喜您，数据已全部导入成功！共 %d 条，数据如下：<br/>%s", len(users), msgStr)})

}
